package com.lianzai.mobile.service.impl;

import com.lianzai.camera.model.CameraInfo;
import com.lianzai.camera.service.CameraService;
import com.lianzai.car.domain.CarLogDO;
import com.lianzai.car.service.CarLogService;
import com.lianzai.common.config.WxConfig;
import com.lianzai.common.executor.LocalSvrSyncExecutor;
import com.lianzai.common.utils.*;
import com.lianzai.common.utils.jackson.Json;
import com.lianzai.mobile.dao.UserAccountDao;
import com.lianzai.mobile.domain.CommunityInfoDO;
import com.lianzai.mobile.domain.UserAccountDO;
import com.lianzai.mobile.domain.WxUserDO;
import com.lianzai.mobile.service.WxNotifyService;
import com.lianzai.mobile.service.WxUserService;
import com.lianzai.payment.domain.OrderInfoDO;
import com.lianzai.payment.service.OrderInfoService;
import com.lianzai.stat.service.StatService;
import com.lianzai.util.TimeUtil;
import com.lianzai.shop.dao.OrderDao;
import com.lianzai.shop.model.TicketOrderDO;
import com.lianzai.ticket.dao.TicketDao;
import com.lianzai.ticket.model.MerchantTicketDO;
import com.lianzai.ticket.model.TicketDiscount;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
public class WxNotifyServiceImpl implements WxNotifyService {

	@Autowired
	private WxConfig wxConfig;

	@Autowired
	private OrderInfoService orderInfoService;

	@Autowired
	private Json json;

	@Autowired
	private WxUserService wxUserService;

	@Autowired
	private UserAccountDao userAccountDao;

	@Autowired
	private CameraService cameraService;

	@Autowired
	private CarLogService carLogService;

       @Autowired
	private StatService statService;

	@Autowired
	private OrderDao ticketOrderDao;

	@Autowired
	private TicketDao ticketDao;

	public UserAccountDO selectUserEndDate(Long userId, Long carId){
		UserAccountDO userAccountDO = userAccountDao.selectUserEndDateByUserIdAndCarId(userId, carId);
		return userAccountDO;
	}

	/**
	 * 微信推送事件处理
	 * @param request
	 * @return
	 */
	public String coreServletPost(HttpServletRequest request){
		try {
			Map<String, String> requestMap = WxUtil.parseXml(request);
			log.info("请求参数：{}", json.obj2string(requestMap));

			String toUserName = requestMap.get("ToUserName");      //开发者微信号
			String fromUserName = requestMap.get("FromUserName");  //发送方帐号（一个OpenID）
			String msgType = requestMap.get("MsgType");            //消息类型，event
			String eventType = requestMap.get("Event");            //事件类型，subscribe(订阅)、unsubscribe(取消订阅)

			if(msgType.equals("event")){  //关注/取关事件
				if(eventType.equals("subscribe")){
					Map<String, Object> params = new HashMap();
					params.put("openId", fromUserName);
					List<WxUserDO> list = wxUserService.list(params);
					if(list != null && list.size()>0){
						WxUserDO wxUserDO = list.get(0);
						wxUserDO.setIsAttention(eventType);
						wxUserService.update(wxUserDO);
					} else {
						WxUserDO wxUserDO = new WxUserDO();
						wxUserDO.setIsAttention(eventType);
						wxUserDO.setAttentionTime(new Date());
						wxUserDO.setOpenId(fromUserName);
						wxUserService.save(wxUserDO);
					}
				}else if(eventType.equals("unsubscribe")){
					Map<String, Object> params = new HashMap();
					params.put("openId", fromUserName);
					List<WxUserDO> list = wxUserService.list(params);
					if(list != null && list.size()>0){
						WxUserDO wxUserDO = list.get(0);
						wxUserDO.setIsAttention(eventType);
						wxUserService.update(wxUserDO);
					}
				}
			}
		}catch (Exception e){
			log.error("处理订阅和取消订阅异常：{}", e.getMessage());
			e.printStackTrace();
		}

		return "SUCCESS";
	}

	/**
	 * 支付回调处理
	 * @param xml
	 * @return
	 */
	public R weixinJsapi(String xml){
		try {
			Map<String,String> parameters = XmlUtils.toMap(xml.getBytes("utf-8"),"utf-8");

			String resultCode = parameters.get("result_code");  //结果

			String message = parameters.get("return_msg");  //消息

			String totalFee = parameters.get("total_fee");  //总金额（分）

			String paymentNo = parameters.get("out_trade_no");  //支付流水号

			String outBizNo = parameters.get("transaction_id");  //微信支付订单号

			String transTime = parameters.get("time_end");  //支付时间

			if(resultCode.equals("SUCCESS")) {
				String sign = parameters.get("sign");
				TreeMap<String, String> paramMap = new TreeMap<String, String>(parameters);
				String signStr = ParamsUtils.map2StrByAscii(paramMap).concat("&key=").concat(wxConfig.getPrivateKey());

				Map<String, Object> params = new HashedMap();
				params.put("orderCode", paymentNo);
				List<OrderInfoDO> list = orderInfoService.list(params);


				if (list != null && list.size() > 0) {

					if (StringUtils.isNotBlank(sign) && sign.equalsIgnoreCase(MD5Util.MD5Encode(signStr))) {
						OrderInfoDO info = list.get(0);
						info.setOrderStatus(1);
						info.setPayAmt(new BigDecimal(totalFee).divide(new BigDecimal("100")));
						info.setPayTime(new SimpleDateFormat("yyyyMMddHHmmss").parse(transTime));
						info.setPayNo(outBizNo);
						orderInfoService.update(info);

		                                /**
						 * 将每一笔收入统计到缴费统计表中
						 * 20190729
						 */
						try{
							CommunityInfoDO communityInfo = cameraService.getCommunityByCameraId(Long.valueOf(info.getExitId()));
							Map map = new HashMap();
							map.put("communityId",communityInfo.getId());
							Date transDate = new SimpleDateFormat("yyyyMMddHHmmss").parse(transTime);
							map.put("periodDate",TimeUtil.getStringDate(transDate));
							List<Map> feeList = statService.queryFeeByDateAndCommunity(map);
							map.put("fee",info.getPayAmt());
							if(feeList != null && feeList.size() >0){
								statService.updateStatFee(map);
							}else{
								statService.insertStatFee(map);
							}
						}catch(Exception e){
							log.error("更新缴费信息失败");
						}

						if (info.getOrderType() == 1) {
							//更新用户到期时间
							UserAccountDO userAccout = userAccountDao.getUserIdAndCarId(info.getUserId(), info.getCarId());
							if (userAccout != null) {
								userAccout.setCarExpireDate(info.getEndTime());
								userAccout.setUpdateTime(new Date());
								userAccountDao.update(userAccout);
							} else {
								userAccout = new UserAccountDO();
								userAccout.setUserId(info.getUserId());
								userAccout.setCarId(info.getCarId());
								userAccout.setCreateTime(new Date());
								userAccout.setCarExpireDate(info.getEndTime());
								userAccountDao.save(userAccout);
							}
						} else if (info.getOrderType() == 2) {
							log.info("更新车辆进出记录中的支付状态");
							CarLogDO carLog = new CarLogDO();
							carLog.setCarNumber(info.getCarNo());
							carLog.setCameraId(Long.valueOf(info.getExitId()));
							carLog.setOrderId(info.getOrderId());
							carLog.setPayTime(info.getPayTime());

							log.info("carNumber={}, cameraId={}, orderId={}, payTime={}",
									carLog.getCarNumber(), carLog.getCameraId(), carLog.getOrderId(), carLog.getPayTime());

							int ret = carLogService.payedByCarNumber(carLog);

							log.info("更新车辆进出记录中的支付状态结果={}", ret);

							log.info("开始调用开闸");
							CommunityInfoDO communityInfo = cameraService.getCommunityByCameraId(Long.valueOf(info.getExitId()));
							log.info("开闸小区信息：{}", communityInfo);
							boolean b = LocalSvrSyncExecutor.informPayResultToLocalSystem(info.getOrderId(), Long.valueOf(info.getExitId()), 1, communityInfo);
							log.info("调用开闸功能！exit_id:{},开闸结果：{}", info.getExitId(), b);
						}

						return R.okObj("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
					}

					OrderInfoDO info = list.get(0);
					info.setOrderStatus(2);
					info.setPayAmt(BigDecimal.valueOf(0));
					info.setPayTime(new SimpleDateFormat("yyyyMMddHHmmss").parse(transTime));
					info.setPayNo(outBizNo);
					orderInfoService.update(info);
					return R.okObj("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>");
				} else {
					//购买停车券支付结果处理
					List<TicketOrderDO> list2 = ticketOrderDao.getByOrderCode(params);

					if (list2 == null || list2.size() <= 0) {
						throw new RuntimeException("流水号异常");
					}


					if (StringUtils.isNotBlank(sign) && sign.equalsIgnoreCase(MD5Util.MD5Encode(signStr))) {

						TicketOrderDO ticketOrder = list2.get(0);

						long freeTicketNum = 0;

						//更新用户停车券概览表
						int totalTicketNum = ticketOrder.getOrderTicketNum().intValue();

						//计算是否有优惠，具体赠送的停车券数量
						List<TicketDiscount> discounts = ticketDao.getTicketDiscountByWXId(ticketOrder.getOpenId());
						if (discounts != null && discounts.size() > 0) {
							int giftNum = 0;

							/**
							 * 循环分析各档优惠，以获取最大优惠为原则
							 * 算法保证即便出现买得更多反而送得更少的异常规则，也能在所有规则范围内，为客户找到最大赠送值
							 * 注：从数据库查询得到的优惠规则，是按购买数量进行了升序排序的
							 */
							for (TicketDiscount discount : discounts) {
								if (ticketOrder.getOrderTicketNum() < discount.getTicketBuyNum()) {
									break;  //优惠搜索结束
								}

								if (discount.getTicketGiftNum() > giftNum) {
									giftNum = discount.getTicketGiftNum();
								}
							}

							totalTicketNum += giftNum;

							freeTicketNum = giftNum;
						}

						MerchantTicketDO merchantTicketDO = ticketDao.getTicketOverview(ticketOrder.getUserId().intValue());

						if (merchantTicketDO != null) {

							merchantTicketDO.setTicketId(ticketOrder.getTicketId().intValue());
							merchantTicketDO.setTicketBuyedNum(totalTicketNum);
							merchantTicketDO.setTicketRemainNum(totalTicketNum);

							int ret = ticketDao.increaseTicket(merchantTicketDO);
						} else {
							merchantTicketDO = new MerchantTicketDO();
							merchantTicketDO.setUserId(ticketOrder.getUserId().intValue());
							merchantTicketDO.setTicketId(ticketOrder.getTicketId().intValue());
							merchantTicketDO.setTicketBuyedNum(totalTicketNum);
							merchantTicketDO.setTicketRemainNum(totalTicketNum);

							int ret = ticketDao.buyTicket(merchantTicketDO);

						}


						//更新订单
						ticketOrder.setOrderStatus(1);
						ticketOrder.setPayTime(new SimpleDateFormat("yyyyMMddHHmmss").parse(transTime));
						ticketOrder.setPayNo(outBizNo);
						ticketOrder.setFreeTicketNum(freeTicketNum);

						ticketOrderDao.updateTicketOrder(ticketOrder);

						return R.okObj("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
					}

					TicketOrderDO ticketOrder = list2.get(0);
					ticketOrder.setOrderStatus(2);
					ticketOrder.setPayAmt(BigDecimal.valueOf(0));
					ticketOrder.setPayTime(new SimpleDateFormat("yyyyMMddHHmmss").parse(transTime));
					ticketOrder.setPayNo(outBizNo);
					ticketOrderDao.updateTicketOrder(ticketOrder);

					return R.okObj("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>");
				}
			}
		} catch (Exception e){
			log.error("处理公众号支付回调业务逻辑异常", e);
		}
		return R.error();
	}
}
